package kp.rpc.protocol.encode;

import io.vertx.core.buffer.Buffer;
import kp.rpc.Enum.ProtocolMessageSerializerEnum;
import kp.rpc.Enum.ProtocolMessageTypeEnum;
import kp.rpc.model.RpcRequest;
import kp.rpc.model.RpcResponse;
import kp.rpc.protocol.ProtocolConstant;
import kp.rpc.protocol.ProtocolMessage;
import kp.rpc.serializer.Serializer;
import kp.rpc.serializer.factory.SerializerFactory;

import java.io.IOException;
import java.util.Objects;

public class ProtocolMessageDecoder {
    /**
     * @param buffer 缓冲区
     * @return kp.rpc.protocol.ProtocolMessage<?>
     * @description: 解码
     * @author tzf
     * @date: 2024/6/6 16:09
     */

    public static ProtocolMessage<?> decode(Buffer buffer) throws IOException {
        //效验魔数
        byte bufferMagic = buffer.getByte(0);
        if (bufferMagic != ProtocolConstant.PROTOCOL_MAGIC) {
            throw new RuntimeException("magic number error");
        }
        ProtocolMessage.Header header = new ProtocolMessage.Header();
        //依次读取数据
        header.setMagic(bufferMagic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getLong(5));
        //long=>8个字节
        header.setBodyLength(buffer.getInt(13));
        //解决tcp传输粘包问题
        byte[] bodyBytes = buffer.getBytes(17, 17 + header.getBodyLength());
        //解析消息体
        ProtocolMessageSerializerEnum serializerByKey = ProtocolMessageSerializerEnum.getEnumByKey(header.getSerializer());
        if (serializerByKey == null) {
            throw new RuntimeException("序列化消息的协议不存在");
        }
        Serializer serializer = SerializerFactory.getInstance(serializerByKey.getValue());
        ProtocolMessageTypeEnum messageTypeEnumByKey = ProtocolMessageTypeEnum.getEnumByKey(header.getType());
        if (messageTypeEnumByKey == null) {
            throw new RuntimeException("序列化消息的类型不存在");
        }
        switch (messageTypeEnumByKey) {
            case REQUEST -> {
                //请求消息
                RpcRequest request = (RpcRequest) serializer.deserialize(bodyBytes, RpcRequest.class);
                return new ProtocolMessage<>(header, request);
            }
            case RESPONSE -> {
                //响应消息
                RpcResponse response = (RpcResponse) serializer.deserialize(bodyBytes, RpcResponse.class);
                return new ProtocolMessage<>(header, response);
            }
            case HEART_BEAT, OTHERS -> {
                return new ProtocolMessage<>();
            }
            default -> {
                throw new RuntimeException("消息类型不支持");
            }
        }
    }
}
